package com.transpot.service.impl.car;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.transpot.entry.car.*;
import com.transpot.mapper.car.CarDriverMapper;
import com.transpot.mapper.car.CarInformationMapper;
import com.transpot.mapper.car.CarMapper;
import com.transpot.mapper.car.InformationMapper;
import com.transpot.service.car.CarService;
import com.transpot.utils.UploadUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 汽车类service层实现类
 */
@Service
public class CarServiceImpl extends ServiceImpl<CarMapper, Car> implements CarService {
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private CarInformationMapper carInformationMapper;
    @Autowired
    private InformationMapper informationMapper;
    @Autowired
    private CarDriverMapper carDriverMapper;
    /**
     * 车辆注册方法的实现
     * @param car
     */
    @Override
    public void registerCar(Car car) {
        //判断车辆的所有人
        if (StringUtils.isBlank(car.getPeople()) || "公司".equals(car.getPeople())) {
            //为公司或者没有所有人则设置为空闲
            car.setStatus(0);
        } else {
            //如果有所有人则设置为使用中，不可分配给其他人
            car.setStatus(1);
        }
        //设置创建时间和修改时间
        car.setCreateTime(LocalDateTime.now());
        car.setUpdateTime(LocalDateTime.now());
        //调用Mapper层方法保存车辆信息
        carMapper.insert(car);
    }

    /**
     * 获取CarVO的分页查询对象方法的实现
     * @param iPage
     * @return
     */
    @Override
    public Page<CarVO> getCarVO(IPage<Car> iPage) {
        //创建一个CarVO列表用来存储拼好的所有对象
        List<CarVO> carVOList = new ArrayList<>();
        //遍历分页对象中的车辆信息对象
        for (int i = 0; i < iPage.getRecords().size(); i ++) {
            //获取到车辆信息对象
            Car car = iPage.getRecords().get(i);
            //获取到车辆主键
            Integer carId = car.getId();
            //设置中间表的条件查询对象
            LambdaQueryWrapper<CarInformation> carInformationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //设置查询条件为与车辆主键相同
            carInformationLambdaQueryWrapper.eq(CarInformation::getCarId, carId);
            //在中间表中查询与车辆主键相同的信息
            CarInformation carInformation = carInformationMapper.selectOne(carInformationLambdaQueryWrapper);
            //创建CarVO对象
            CarVO carVO = new CarVO();
            //把车辆对象里的信息复制到CarVO对象中
            BeanUtils.copyProperties(car, carVO);
            //因为个人的车辆没有添加图片信息，因此要判断中间表是否为空
            if (carInformation != null) {
                //获取到图片信息主键
                Integer informationId = carInformation.getInformationId();
                //根据图片信息主键查询图片信息
                Information information = informationMapper.selectById(informationId);
                //把图片信息设置到carVO对象中
                carVO.setImgUrl1(information.getImgUrl1());
                carVO.setImgUrl2(information.getImgUrl2());
                carVO.setImgUrl3(information.getImgUrl3());
            }
            //把carVO对象添加到列表中
            carVOList.add(carVO);
        }
        //创建CarVO类型的分页对象
        Page<CarVO> page = new Page<>(iPage.getCurrent(), iPage.getSize());
        //设置总查询条数
        page.setTotal(iPage.getTotal());
        //设置查询信息
        page.setRecords(carVOList);
        return page;
    }

    /**
     * 根据车辆信息删除车辆
     * @param id
     */
    @Override
    public void deleteCarById(Integer id) {
        //创建车辆和图片信息中间类条件查询对象
        LambdaQueryWrapper<CarInformation> carInformationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与车辆主键相同
        carInformationLambdaQueryWrapper.eq(CarInformation::getCarId, id);
        //查询车辆和图片信息中间类信息
        CarInformation carInformation = carInformationMapper.selectOne(carInformationLambdaQueryWrapper);
        //根据中间类信息获得图片信息的主键
        Integer informationId = carInformation.getInformationId();
        //删除图片信息
        informationMapper.deleteById(informationId);
        //删除中间类关联
        carInformationMapper.delete(carInformationLambdaQueryWrapper);
        //创建车辆和司机中间类条件查询对象
        LambdaQueryWrapper<CarDriver> carDriverLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与车辆主键一致
        carDriverLambdaQueryWrapper.eq(CarDriver::getCarId, id);
        //删除车辆与司机的关联
        carDriverMapper.delete(carDriverLambdaQueryWrapper);
        //删除车辆信息
        carMapper.deleteById(id);
    }

    /**
     * 修改车辆信息和图片方法实现
     * @param carVO
     * @param files
     */
    @Override
    public void updateWithPicture(CarVO carVO, MultipartFile[] files) {
        //创建车辆信息对象
        Car car = new Car();
        //把carVO中的车辆信息复制到car对象中
        BeanUtils.copyProperties(carVO, car);
        //设置最后一次修改时间为当前
        car.setUpdateTime(LocalDateTime.now());
        //修改车辆基本信息
        carMapper.updateById(car);
        //创建车辆和图片信息中间类的条件查询对象
        LambdaQueryWrapper<CarInformation> carInformationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为车辆主键
        carInformationLambdaQueryWrapper.eq(CarInformation::getCarId, car.getId());
        //查询车辆和图片信息的关联
        CarInformation carInformation = carInformationMapper.selectOne(carInformationLambdaQueryWrapper);
        //如果能查到关联，因为如果车辆是司机所有的则注册时没有图片
        if (carInformation != null) {
            //如果存在则查询到图片信息
            Information information = informationMapper.selectById(carInformation.getInformationId());
            //替换图片逻辑
            //设置标记数组，代表当前位置是否更改过
            boolean[] status = new boolean[4];
            /**
             * 因为前端对图片文件的是否修改的判断是按顺序的，因此图片信息的更改也是按顺序的，
             * 我们按顺序遍历添加的文件信息，去按顺序判断哪张图片的路径变更了，则该图片属于该变量
             * 更改即可，但是注意更改过得图片就不能更改了
             */
            for (MultipartFile multipartFile : files) {
                //如果有图片路径信息并且该位置没更新过，即要么原来就有图片，要么就是没有新加了图片
                if (carVO.getImgUrl1() != null && !status[1]) {
                    //如果原本的图片信息里为空，则该位置一定被修改，或者是原来的图片信息和现在的不一样，则证明图片信息也被修改
                    if (information.getImgUrl1() == null || (information.getImgUrl1() != null && !information.getImgUrl1().equals(carVO.getImgUrl1()))) {
                        //把新的图片存到本地
                        String imgUrl = UploadUtil.uploadImg(multipartFile);
                        //设置新的路径
                        information.setImgUrl1(imgUrl);
                        //标记该位置为已经更新
                        status[1] = true;
                    }
                }
                if (carVO.getImgUrl2() != null && !status[2]) {
                    if (information.getImgUrl2() == null || (information.getImgUrl2() != null && !information.getImgUrl2().equals(carVO.getImgUrl2()))) {
                        String imgUrl = UploadUtil.uploadImg(multipartFile);
                        information.setImgUrl2(imgUrl);
                        status[2] = true;
                    }
                }
                if (carVO.getImgUrl3() != null && !status[3]) {
                    if (information.getImgUrl3() == null || (information.getImgUrl3() != null && !information.getImgUrl3().equals(carVO.getImgUrl3()))) {
                        String imgUrl = UploadUtil.uploadImg(multipartFile);
                        information.setImgUrl3(imgUrl);
                        status[3] = true;
                    }
                }
            }
            //修改图片信息
            informationMapper.updateById(information);
        } else {
            //如果不存在则创建一个新的对象
            Information information = new Information();
            boolean[] status = new boolean[4];
            /**
             * 因为前端对图片文件的是否修改的判断是按顺序的，因此图片信息的更改也是按顺序的，
             * 我们按顺序遍历添加的文件信息，去按顺序判断哪张图片的路径变更了，则该图片属于该变量
             * 更改即可，但是注意更改过得图片就不能更改了
             */
            for (MultipartFile multipartFile : files) {
                if (carVO.getImgUrl1() != null && !status[1]) {
                    String imgUrl = UploadUtil.uploadImg(multipartFile);
                    information.setImgUrl1(imgUrl);
                    status[1] = true;
                } else if (carVO.getImgUrl2() != null && !status[2]) {
                    String imgUrl = UploadUtil.uploadImg(multipartFile);
                    information.setImgUrl2(imgUrl);
                    status[2] = true;
                } else if (carVO.getImgUrl3() != null && !status[3]) {
                    String imgUrl = UploadUtil.uploadImg(multipartFile);
                    information.setImgUrl3(imgUrl);
                    status[3] = true;
                }
            }
            //把新建的图片信息插入到数据库中
            informationMapper.insert(information);
            //创建车辆和图片信息中间类对象，建立新的关联
            CarInformation newCarInformation = new CarInformation();
            //设置图片信息主键
            newCarInformation.setInformationId(information.getId());
            //设置车辆信息主键
            newCarInformation.setCarId(car.getId());
            //插入数据库
            carInformationMapper.insert(newCarInformation);
        }
    }

    /**
     * 根据登录的角色的id获取到与之关联的车辆信息方法的实现
     * @param id
     * @return
     */
    @Override
    public List<CarVO> getCarListById(Integer id) {
        //创建司机车辆中间表条件查询对象
        LambdaQueryWrapper<CarDriver> carDriverLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与司机的主键相同
        carDriverLambdaQueryWrapper.eq(CarDriver::getDriverId, id);
        //查询司机车辆关联信息
        List<CarDriver> carDriverList = carDriverMapper.selectList(carDriverLambdaQueryWrapper);
        //创建汽车列表，用来存储车辆信息
        List<CarVO> carList = new ArrayList<>();
        //遍历所有的中间类对象
        for (CarDriver carDriver : carDriverList) {
            //获取车辆主键
            Integer carId = carDriver.getCarId();
            //根据车辆主键获取到车辆信息
            Car car = carMapper.selectById(carId);
            //创建CarVO对象
            CarVO carVO = new CarVO();
            //把车辆基础信息复制到carVO对象中
            BeanUtils.copyProperties(car, carVO);
            //创建车辆和图片信息中间类条件查询对象
            LambdaQueryWrapper<CarInformation> carInformationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //设置查询条件为与车辆主键相同
            carInformationLambdaQueryWrapper.eq(CarInformation::getCarId, carId);
            //查询中间类对象
            CarInformation carInformation = carInformationMapper.selectOne(carInformationLambdaQueryWrapper);
            if (carInformation != null) {
                //根据图片主键查询图片信息
                Information information = informationMapper.selectById(carInformation.getInformationId());
                //设置图片信息
                carVO.setImgUrl1(information.getImgUrl1());
                carVO.setImgUrl2(information.getImgUrl2());
                carVO.setImgUrl3(information.getImgUrl3());
            }
            //把图片存入列表
            carList.add(carVO);
        }
        return carList;
    }
}
